<template>
  <div class="file-uploader">
    <div class="file-selector">
      <input 
        type="file" 
        ref="fileInput" 
        @change="handleFileChange" 
        multiple 
        class="file-input"
      />
      <button @click="triggerFileInput" class="select-btn">选择文件</button>
    </div>

    <div v-if="selectedFiles.length > 0" class="file-list">
      <h3>已选择的文件</h3>
      <div v-for="(file, index) in selectedFiles" :key="index" class="file-item">
        <div class="file-info">
          <span class="file-name">{{ file.name }}</span>
          <span class="file-size">{{ formatFileSize(file.size) }}</span>
          <span class="file-type">{{ file.type || '未知类型' }}</span>
        </div>
        <div class="progress-container">
          <div class="progress-bar">
            <div 
              class="progress" 
              :style="{ width: file.progress + '%' }"
              :class="{ 'progress-error': file.error }"
            ></div>
          </div>
          <span class="progress-text">{{ file.progress }}%</span>
        </div>
        <div class="file-actions">
          <button 
            v-if="!file.uploading && !file.completed" 
            @click="uploadFile(index)" 
            class="action-btn upload-btn"
          >
            上传
          </button>
          <button 
            v-if="file.uploading && !file.paused" 
            @click="pauseUpload(index)" 
            class="action-btn pause-btn"
          >
            暂停
          </button>
          <button 
            v-if="file.paused" 
            @click="resumeUpload(index)" 
            class="action-btn resume-btn"
          >
            继续
          </button>
          <button 
            v-if="file.uploading || file.paused" 
            @click="cancelUpload(index)" 
            class="action-btn cancel-btn"
          >
            取消
          </button>
          <button 
            v-if="file.error" 
            @click="retryUpload(index)" 
            class="action-btn retry-btn"
          >
            重试
          </button>
        </div>
        <div v-if="file.error" class="error-message">
          {{ file.errorMessage }}
        </div>
      </div>
    </div>

    <div v-if="selectedFiles.length > 0" class="overall-progress">
      <h3>总体进度</h3>
      <div class="progress-container">
        <div class="progress-bar">
          <div 
            class="progress" 
            :style="{ width: overallProgress + '%' }"
          ></div>
        </div>
        <span class="progress-text">{{ overallProgress }}%</span>
      </div>
      <div class="upload-actions">
        <button 
          v-if="!allCompleted && !uploading" 
          @click="uploadAll" 
          class="action-btn upload-all-btn"
        >
          上传所有
        </button>
        <button 
          v-if="uploading && !allPaused" 
          @click="pauseAll" 
          class="action-btn pause-all-btn"
        >
          全部暂停
        </button>
        <button 
          v-if="allPaused" 
          @click="resumeAll" 
          class="action-btn resume-all-btn"
        >
          全部继续
        </button>
        <button 
          v-if="uploading || allPaused" 
          @click="cancelAll" 
          class="action-btn cancel-all-btn"
        >
          全部取消
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import { uploadChunk, mergeChunks, getUploadStatus } from '../services/uploadService';

export default {
  name: 'FileUploader',
  setup() {
    const fileInput = ref(null);
    const selectedFiles = ref([]);
    const chunkSize = 1024 * 1024; // 1MB

    // 计算总体上传进度
    const overallProgress = computed(() => {
      if (selectedFiles.value.length === 0) return 0;
      
      const totalProgress = selectedFiles.value.reduce((sum, file) => sum + file.progress, 0);
      return Math.floor(totalProgress / selectedFiles.value.length);
    });

    // 计算是否所有文件都已完成上传
    const allCompleted = computed(() => {
      return selectedFiles.value.length > 0 && 
             selectedFiles.value.every(file => file.completed);
    });

    // 计算是否有文件正在上传
    const uploading = computed(() => {
      return selectedFiles.value.some(file => file.uploading && !file.paused);
    });

    // 计算是否所有正在上传的文件都已暂停
    const allPaused = computed(() => {
      const uploadingFiles = selectedFiles.value.filter(file => file.uploading);
      return uploadingFiles.length > 0 && uploadingFiles.every(file => file.paused);
    });

    // 触发文件选择框
    const triggerFileInput = () => {
      fileInput.value.click();
    };

    // 处理文件选择变化
    const handleFileChange = (event) => {
      const files = Array.from(event.target.files);
      
      files.forEach(file => {
        selectedFiles.value.push({
          file,
          name: file.name,
          size: file.size,
          type: file.type,
          progress: 0,
          chunks: [],
          uploadedChunks: [],
          uploading: false,
          paused: false,
          completed: false,
          error: false,
          errorMessage: '',
          fileId: generateFileId(file),
          controller: null // AbortController 实例
        });
      });
      
      // 重置文件输入，允许重新选择相同的文件
      event.target.value = '';
    };

    // 生成文件唯一标识
    const generateFileId = (file) => {
      return `${file.name}-${file.size}-${Date.now()}`;
    };

    // 格式化文件大小
    const formatFileSize = (bytes) => {
      if (bytes === 0) return '0 Bytes';
      
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    };

    // 将文件分片
    const sliceFile = (file) => {
      const chunks = [];
      const chunksCount = Math.ceil(file.size / chunkSize);
      
      for (let i = 0; i < chunksCount; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.file.slice(start, end);
        
        chunks.push({
          index: i,
          data: chunk,
          size: chunk.size,
          uploaded: false
        });
      }
      
      return chunks;
    };

    // 上传单个文件
    const uploadFile = async (index) => {
      const file = selectedFiles.value[index];
      
      if (file.uploading || file.completed) return;
      
      file.uploading = true;
      file.paused = false;
      file.error = false;
      file.errorMessage = '';
      
      // 如果文件还没有分片，则进行分片
      if (file.chunks.length === 0) {
        file.chunks = sliceFile(file);
        file.uploadedChunks = new Array(file.chunks.length).fill(false);
      }
      
      // 创建 AbortController 用于取消上传
      file.controller = new AbortController();
      
      try {
        // 并发上传分片
        const uploadPromises = [];
        
        for (let i = 0; i < file.chunks.length; i++) {
          if (!file.uploadedChunks[i] && !file.paused) {
            uploadPromises.push(uploadChunk(i, file));
          }
        }
        
        await Promise.all(uploadPromises);
        
        // 如果没有被取消或暂停，且所有分片都已上传，则合并分片
        if (!file.paused && file.uploadedChunks.every(uploaded => uploaded)) {
          await mergeChunks(file.fileId);
          file.completed = true;
          file.uploading = false;
          file.progress = 100;
        }
      } catch (error) {
        if (error.name !== 'AbortError') {
          file.error = true;
          file.errorMessage = `上传失败: ${error.message}`;
        }
        file.uploading = false;
      }
    };

    // 暂停上传
    const pauseUpload = (index) => {
      const file = selectedFiles.value[index];
      
      if (file.uploading && !file.paused) {
        file.paused = true;
        if (file.controller) {
          file.controller.abort();
          file.controller = null;
        }
      }
    };

    // 继续上传
    const resumeUpload = (index) => {
      const file = selectedFiles.value[index];
      
      if (file.paused) {
        file.paused = false;
        uploadFile(index);
      }
    };

    // 取消上传
    const cancelUpload = (index) => {
      const file = selectedFiles.value[index];
      
      if (file.uploading || file.paused) {
        if (file.controller) {
          file.controller.abort();
          file.controller = null;
        }
        
        file.uploading = false;
        file.paused = false;
        file.progress = 0;
        file.chunks = [];
        file.uploadedChunks = [];
      }
    };

    // 重试上传
    const retryUpload = (index) => {
      const file = selectedFiles.value[index];
      
      if (file.error) {
        file.error = false;
        file.errorMessage = '';
        uploadFile(index);
      }
    };

    // 上传所有文件
    const uploadAll = () => {
      selectedFiles.value.forEach((file, index) => {
        if (!file.uploading && !file.completed) {
          uploadFile(index);
        }
      });
    };

    // 全部暂停
    const pauseAll = () => {
      selectedFiles.value.forEach((file, index) => {
        if (file.uploading && !file.paused) {
          pauseUpload(index);
        }
      });
    };

    // 全部继续
    const resumeAll = () => {
      selectedFiles.value.forEach((file, index) => {
        if (file.paused) {
          resumeUpload(index);
        }
      });
    };

    // 全部取消
    const cancelAll = () => {
      selectedFiles.value.forEach((file, index) => {
        if (file.uploading || file.paused) {
          cancelUpload(index);
        }
      });
    };

    return {
      fileInput,
      selectedFiles,
      overallProgress,
      allCompleted,
      uploading,
      allPaused,
      triggerFileInput,
      handleFileChange,
      formatFileSize,
      uploadFile,
      pauseUpload,
      resumeUpload,
      cancelUpload,
      retryUpload,
      uploadAll,
      pauseAll,
      resumeAll,
      cancelAll
    };
  }
};
</script>

<style scoped>
.file-uploader {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.file-selector {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
}

.file-input {
  display: none;
}

.select-btn {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
  transition: background-color 0.3s;
}

.select-btn:hover {
  background-color: #45a049;
}

.file-list {
  margin-bottom: 20px;
}

.file-item {
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
  margin-bottom: 10px;
  background-color: #f9f9f9;
}

.file-info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}

.file-name {
  font-weight: bold;
  flex: 2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-size, .file-type {
  flex: 1;
  text-align: right;
  color: #666;
}

.progress-container {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.progress-bar {
  flex: 1;
  height: 20px;
  background-color: #e0e0e0;
  border-radius: 10px;
  overflow: hidden;
  margin-right: 10px;
}

.progress {
  height: 100%;
  background-color: #4CAF50;
  transition: width 0.3s ease;
}

.progress-error {
  background-color: #f44336;
}

.progress-text {
  min-width: 40px;
  text-align: right;
}

.file-actions {
  display: flex;
  gap: 10px;
}

.action-btn {
  padding: 5px 10px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
}

.upload-btn, .upload-all-btn {
  background-color: #4CAF50;
  color: white;
}

.pause-btn, .pause-all-btn {
  background-color: #ff9800;
  color: white;
}

.resume-btn, .resume-all-btn {
  background-color: #2196F3;
  color: white;
}

.cancel-btn, .cancel-all-btn {
  background-color: #f44336;
  color: white;
}

.retry-btn {
  background-color: #9c27b0;
  color: white;
}

.action-btn:hover {
  opacity: 0.9;
}

.error-message {
  color: #f44336;
  margin-top: 10px;
  font-size: 14px;
}

.overall-progress {
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 15px;
  background-color: #f9f9f9;
}

.upload-actions {
  display: flex;
  gap: 10px;
  margin-top: 10px;
}

@media (max-width: 600px) {
  .file-info {
    flex-direction: column;
  }
  
  .file-size, .file-type {
    text-align: left;
    margin-top: 5px;
  }
  
  .file-actions {
    flex-wrap: wrap;
  }
}
</style>